﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.ClientEngine;
using IPrinting;
using System.Threading;
using LogLib;
using System.Net;
using ComLib.ComType;

namespace PhotoPrintClient
{
    public class PrintClient
    {
        private static ClientConfig _config = new ClientConfig();

        private EasyClient<PrintResponsePackageInfo> _client = null;
       
        private bool _connected = false;
        public bool Connected
        {
            get { return _connected; }
        }

        /// <summary>
        /// 指示Socket连接动作是否已经完成
        /// </summary>
        private bool _connectCompleted = false;

        private string _error = "";
        public string Error
        {
            get { return _error; }
        }

        public event PrintClientPackageReceivedEventHandler ClientPackageReceived;
        protected void OnClientPackageReceived(PrintResponsePackge pack)
        {
            if (ClientPackageReceived != null)
            {
                ClientPackageReceived(this, new PrintClientPackageReceivedEventArgs(pack));
            }
        }

        public event ClientErrorReportedEventHandler ErrorReported;
        protected void OnClientErrorReported(string error)
        {
            if (ErrorReported != null)
            {
                ErrorReported(this, new ErrorReportedEventArgs(error));
            }
        }

        public PrintClient()
        {
            _client = new EasyClient<PrintResponsePackageInfo>();
            _client.Connected += OnClientConnected;
            _client.NewPackageReceived += OnPackageReceived;
            _client.Error += OnClientError;
            _client.Closed += OnClientClosed;
        }

        public void ConnectToServer()
        {           
            _client.Initialize(new PrintResponseReceiveFilter());
            _client.ConnectAsync(new IPEndPoint(IPAddress.Parse(_config.Ip), _config.Port));
            SpinWait.SpinUntil(()=>_connectCompleted);
        }

        private void OnPackageReceived(object sender, PackageEventArgs<PrintResponsePackageInfo> e)
        {
            PrintResponsePackageInfo packageInfo = e.Package;
            PrintResponsePackge pack = packageInfo.Packge;
            OnClientPackageReceived(pack);
        }

        private void OnClientConnected(object sender, EventArgs e)
        {
            _connectCompleted = true;
            _connected = true;
            Log.WriteAsync("已连接到服务器: " + _client.LocalEndPoint.ToString());
        }

        private void OnClientClosed(object sender, EventArgs e)
        {
            _connectCompleted = true;
            _connected = false;
            Log.WriteAsync("连接已断开...");
        }

        private void OnClientError(object sender, ErrorEventArgs e)
        {
            _error = e.Exception.ToString();
            Log.WriteAsync("客户端错误：" + e.Exception.ToString());
            OnClientErrorReported(e.Exception.ToString());
        }

        public void Close()
        {
            ClientPackageReceived = null;
            try
            {
                if (_connected && _client != null)
                {
                    if (_client.IsConnected)
                    {
                        _client.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
            }
        }

        /// <summary>
        /// 向服务器发送执行某种接口操作的请求
        /// </summary>
        /// <param name="request"></param>
        public bool SendRequest(PrintDataPackge request)
        {
            try
            {
                byte[] dataBody = MsgPackHandler.ConvertToBytes<PrintDataPackge>(request);
                // 协议命令占16位
                var commandData = Encoding.UTF8.GetBytes(request.Action);
                // 长度int类型占4位
                var dataLen = BitConverter.GetBytes(dataBody.Length);
                // 命令加内容长度为20
                var sendData = new byte[20 + dataBody.Length];
                // +-------+---+-------------------------------+
                // |request |  l |                               |
                // | name   | e |    request body       |
                // |  (16 )    | n |                               |
                // |             |(4)|                               |
                // +-------+---+-------------------------------+
                Array.ConstrainedCopy(commandData, 0, sendData, 0, commandData.Length);
                Array.ConstrainedCopy(dataLen, 0, sendData, 16, 4);
                Array.ConstrainedCopy(dataBody, 0, sendData, 20, dataBody.Length);
                _client.Send(sendData);
                return true;
            }
            catch (Exception ex)
            {
                _error = ex.ToString();
                Log.WriteException(ex.ToString());
                return false;
            }           
        }
    }
}
